﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace MyTask.WebApi.Filters
{
    public class LogAttribute : ActionFilterAttribute
    {
        #region Private variable
        private readonly ILogger<LogAttribute> _logger;
        private string LogFlag { get; set; }
        private string ActionArguments { get; set; }
        /// <summary>
        /// All values in the request body
        /// </summary>
        private string RequestBody { get; set; }
        private Stopwatch Stopwatch { get; set; }
        #endregion
        #region Constructor
        public LogAttribute(ILogger<LogAttribute> logger)
        {
            _logger = logger;
        }
        #endregion

        #region Overtide method

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            base.OnActionExecuting(context);

            //The request body of the get request was added later, if you don't need to delete it in the actual project
            long contentLen = context.HttpContext.Request.ContentLength == null ? 0 : context.HttpContext.Request.ContentLength.Value;
            if (contentLen > 0)
            {
                // Read everything in the request body
                System.IO.Stream stream = context.HttpContext.Request.Body;
                if (context.HttpContext.Request.Method == "POST")
                {
                    stream.Position = 0;
                }
                byte[] buffer = new byte[contentLen];
                stream.Read(buffer, 0, buffer.Length);
                // Convert to string
                RequestBody = System.Text.Encoding.UTF8.GetString(buffer);
            }

            ActionArguments = Newtonsoft.Json.JsonConvert.SerializeObject(context.ActionArguments);

            Stopwatch = new Stopwatch();
            Stopwatch.Start();
        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
            Stopwatch.Stop();

            string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
            string method = context.HttpContext.Request.Method;

            string qs = ActionArguments;

            dynamic result = context.Result.GetType().Name == "EmptyResult" ? new { Value = "无返回结果" } : context.Result as dynamic;

            string res = "An exception occurred before the result was returned";
            try
            {
                if (result != null)
                {
                    res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);
                }
            }
            catch (System.Exception)
            {
                res = "No results are obtained in the log, and the returned data cannot be serialized";
            }


            _logger.LogInformation($"\n Method：{LogFlag} \n " +
                $"Url：{url} \n " +
                $"Request method：{method} \n " +
                $"Request：{RequestBody} \n " +
                $"Param：{qs}\n " +
                $"Result：{res}\n " +
                $"Time：{Stopwatch.Elapsed.TotalMilliseconds} ms（Refers to the time when the corresponding method in the controller is executed.）");
        }

        #endregion
    }
}
